Fortran For Fun之析构函数final

fortran程序的内存管理很不方便,对于自定义的数据类型需要在程序中手动分配和释放内存,但有时候可能会忘记释放内存,造成内存泄露。所以对于自定义的数据类型最好绑定一个final程序,该程序会在这个类的对象需要销毁的地方自动调用。这些地方包括:

  • 程序结束
  • 传递给intent(out)形参
  • deallocate
  • 等号左边

以下通过learn_final模块进行说明。

learn_final 模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module learn_final
implicit none
!=============================================================================
type foo
real,allocatable :: v(:)
contains
procedure :: allocate => foo_allocate
procedure :: destory => foo_destory
final :: foo_final, foo_final_array
end type foo
contains
!=============================================================================
subroutine foo_allocate(this, n)
class(foo), intent(out) :: this
integer, intent(in) :: n
allocate(this%v(n))
end subroutine foo_allocate
!=============================================================================
elemental subroutine foo_destory(this)
class(foo), intent(inout) :: this
if(allocated(this%v)) deallocate(this%v)
end subroutine foo_destory
!=============================================================================
subroutine foo_final(this)
type(foo), intent(inout) :: this
call this%destory()
print*, 'call final'
end subroutine foo_final
!=============================================================================
subroutine foo_final_array(this)
type(foo), intent(inout) :: this(:)
call this%destory()
print*, 'call final_array'
end subroutine foo_final_array
end module learn_final

final程序的输入只有一个参数,类型必须使用type而不是class,intent属性不能为(out)。 参数可以是标量或数组,也可以是elemental 程序。在该模块中为了测试在哪儿会自动调用final程序,在final程序中有 print 子句,所以不能为elemental程序。

程序结束

在程序结束会自动调用。

1
2
3
4
5
6
7
program main
implicit none
type(foo) :: bar
bar = foo()
print*, "test auto deallocate when end subroutine."
print*, 'end procedure'
end program main

结果

1
2
3
test auto deallocate when end subroutine.
end procedure
call final

可以看到在程序结束的时候自动调用了final程序。

intent(out)

传递给intent(out)形参会自动调用。

1
2
3
4
5
6
7
program main
implicit none
type(foo) :: bar
print*, "test auto deallocate when intent(out)."
call bar%allocate(4)
print*, 'end procedure'
end program main

结果

1
2
3
4
test auto deallocate when intent(out).
call final
end procedure
call final

可以看出程序在调用 allocate函数以及程序结束时都调用了final程序。

deallcate

使用deallocate释放内存。

1
2
3
4
5
6
7
8
program main
implicit none
type(foo), allocatable:: bar(:)
print*, "test auto deallocate by deallocate"
allocate(bar(3))
deallocate(bar)
print*, 'end procedure'
end program main

结果

1
2
3
test auto deallocate when deallocate
call final_array
end procedure

可以看出程序在调用deallocate时调用了final程序。